/*
 * Copyright (c) 2008 Benoit Bouchez, Nicolas Giard
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.noocodecommit.wicket.stuff.jquery.core;

import org.apache.wicket.Component;

import com.noocodecommit.wicket.stuff.jquery.behavior.AbstractDefaultJQBehavior;

/**
 * JQCoreUtils is used to ease small jquery script writting Everywhere you can write javascript in your application, you can use this class to help.<br>
 * JQCoreUtils is not designed to write large scripts such as plugins.<br>
 * When you use this class be careful to the performance lack in your application.<br>
 * JQCoreUtils uses a StringBuilder to chain jquery functions, so performance is directly dependant on StringBuilder performance.<br>
 * <p>
 * Notice that JQCoreUtils is only a jquery function chaining tool.<br>
 * It DOES NOT check JQuery API and errors in function chains.
 * </p>
 * JQuery API documentation is available at : http://docs.jquery.com<br>
 * All javadocs for this class where written with the help of the excellent <a href="http://remysharp.com/jquery-api/">JQuery API Browser</a>
 * 
 * @author Benoit Bouchez
 */
public class JQCoreUtils
{
	/**
	 * Gets JQuery object<br>
	 * Equivalent to "$".
	 * 
	 * @return
	 */
	public static JQScriptBuilder $()
	{
		return new JQScriptBuilder();
	}

	/**
	 * Gets JQuery object<br>
	 * Equivalent to "$(html)".
	 * 
	 * @param html
	 *            html string
	 * @return
	 */
	public static JQScriptBuilder $(String html)
	{
		return new JQScriptBuilder(html);
	}

	/**
	 * Gets JQuery object<br>
	 * Equivalent to "$(element)".
	 * 
	 * @param element
	 *            DOM element
	 * @return
	 */
	public static JQScriptBuilder $(JQDomElement element)
	{
		return new JQScriptBuilder(element);
	}

	/**
	 * Gets JQuery object<br>
	 * Equivalent to "$('#component.id')".
	 * 
	 * @param component
	 *            wicket component
	 * @return
	 */
	public static JQScriptBuilder $(Component component)
	{
		return new JQScriptBuilder(component);
	}

	/**
	 * Gets JQuery object<br>
	 * Equivalent to "$(function(){})".<br>
	 * Shrothand for "$(document).ready()"
	 * 
	 * @param callback
	 *            callback function
	 * @return
	 */
	public static JQScriptBuilder $(JQFunction callback)
	{
		return new JQScriptBuilder(callback);
	}

	/**
	 * Gets JQuery object<br>
	 * Equivalent to "$(function(){})".<br>
	 * Shrothand for "$(document).ready()"
	 * 
	 * @param callback
	 *            callback wicket behavior
	 * @return
	 */
	public static JQScriptBuilder $(AbstractDefaultJQBehavior callback)
	{
		return new JQScriptBuilder(new JQFunction(callback));
	}

	/**
	 * Gets JQuery object<br>
	 * Equivalent to "$(expression, context)".<br>
	 * 
	 * @param expression
	 *            css selector
	 * @param context
	 *            matching context
	 * @return
	 */
	public static JQScriptBuilder $(String expression, JQDomElement context)
	{
		return new JQScriptBuilder(expression, context);
	}

	/**
	 * Gets JQuery object<br>
	 * Equivalent to "$(expression, context)".<br>
	 * 
	 * @param expression
	 *            css selector
	 * @param context
	 *            matching context
	 * @return
	 */
	public static JQScriptBuilder $(String expression, JQScriptBuilder context)
	{
		return new JQScriptBuilder(expression, context);
	}

	/**
	 * @author Benoit Bouchez
	 */
	public static final class JQScriptBuilder
	{
		private StringBuilder scriptBuilder = new StringBuilder();

		/**
		 * Constructor
		 */
		public JQScriptBuilder()
		{
			scriptBuilder.append("$");
		}

		/**
		 * Constructor
		 * 
		 * @param html
		 *            html string
		 */
		public JQScriptBuilder(String html)
		{
			scriptBuilder.append("$('" + html + "')");
		}

		/**
		 * Constructor
		 * 
		 * @param element
		 *            DOM element
		 */
		public JQScriptBuilder(JQDomElement element)
		{
			scriptBuilder.append("$(" + element + ")");
		}

		/**
		 * Constructor
		 * 
		 * @param component
		 *            wicket component
		 */
		public JQScriptBuilder(Component component)
		{
			scriptBuilder.append("$('" + JQSelectorBuilder.id(component) + "')");
		}

		/**
		 * Constructor
		 * 
		 * @param callback
		 *            callback function
		 */
		public JQScriptBuilder(JQFunction callback)
		{
			scriptBuilder.append("$(" + callback + ")");
		}

		/**
		 * Constructor
		 * 
		 * @param callback
		 *            callback wicket behavior
		 */
		public JQScriptBuilder(AbstractDefaultJQBehavior callback)
		{
			this(new JQFunction(callback));
		}

		/**
		 * Constructor
		 * 
		 * @param expression
		 *            css selector
		 * @param context
		 *            mathing expression
		 */
		public JQScriptBuilder(String expression, JQDomElement context)
		{
			scriptBuilder.append("$('" + expression + "', " + context + ")");
		}

		/**
		 * Constructor
		 * 
		 * @param expression
		 *            css selector
		 * @param context
		 *            mathing expression
		 */
		public JQScriptBuilder(String expression, JQScriptBuilder context)
		{
			scriptBuilder.append("$('" + expression + "', " + context + ")");
		}

		/**
		 * Execute a function within the context of every matched element.
		 * 
		 * @param callback
		 *            executed function
		 * @return
		 */
		public JQScriptBuilder each(JQFunction callback)
		{
			this.scriptBuilder.append(".each(" + callback + ")");
			return this;
		}

		/**
		 * Execute a function within the context of every matched element.
		 * 
		 * @param callback
		 *            executed function
		 * @return
		 */
		public JQScriptBuilder each(AbstractDefaultJQBehavior callback)
		{
			return this.each(new JQFunction(callback));
		}

		/**
		 * Reduce the set of matched elements to a single element.<br>
		 * The position of the element in the set of matched elements starts at 0 and goes to length - 1.
		 * 
		 * @param position
		 *            position of the element
		 * @return
		 */
		public JQScriptBuilder eq(Float position)
		{
			this.scriptBuilder.append(".eq(" + position + ")");
			return this;
		}

		/**
		 * Access all matched DOM elements.
		 * 
		 * @return
		 */
		public JQScriptBuilder get()
		{
			this.scriptBuilder.append(".get()");
			return this;
		}

		/**
		 * Access a single matched DOM element at a specified index in the matched set.
		 * 
		 * @param index
		 *            index of the element
		 * @return
		 */
		public JQScriptBuilder get(Float index)
		{
			this.scriptBuilder.append(".get(" + index + ")");
			return this;
		}

		/**
		 * Searches every matched element for the object and returns the index of the element, if found.<br>
		 * starting with zero.
		 * 
		 * @param subject
		 *            searched element
		 * @return
		 */
		public JQScriptBuilder index(JQDomElement subject)
		{
			this.scriptBuilder.append(".index(" + subject + ")");
			return this;
		}

		/**
		 * The number of elements in the jQuery object
		 * 
		 * @return
		 */
		public JQScriptBuilder length()
		{
			this.scriptBuilder.append(".length");
			return this;
		}

		/**
		 * The number of elements in the jQuery object.
		 * 
		 * @return
		 */
		public JQScriptBuilder size()
		{
			this.scriptBuilder.append(".size()");
			return this;
		}

		/**
		 * Extends the jQuery object itself.<br>
		 * Can be used to add functions into the jQuery namespace.
		 * 
		 * @param object
		 *            object enclosing functions definitions
		 * @return
		 */
		public JQScriptBuilder extend(JQObject object)
		{
			this.scriptBuilder.append("$.extend(" + object + ")");
			return this;
		}

		/**
		 * Extends the jQuery element set to provide new methods.<br>
		 * 
		 * @param object
		 *            object enclosing functions definitions
		 * @return
		 */
		public JQScriptBuilder fnExtend(JQObject object)
		{
			this.scriptBuilder.append("$.fn.extend(" + object + ")");
			return this;
		}

		/**
		 * Run this function to give control of the $ variable back to whichever library first implemented it.<br>
		 * This helps to make sure that jQuery doesn't conflict with the $ object of other libraries.
		 * 
		 * @return
		 */
		public JQScriptBuilder noConflict()
		{
			this.scriptBuilder.append("$.noConflict()");
			return this;
		}

		/**
		 * Revert control of both the $ and jQuery variables to their original owners.
		 * 
		 * @return
		 */
		public JQScriptBuilder noConflictExtreme()
		{
			this.scriptBuilder.append("$.noConflict(true)");
			return this;
		}

		/**
		 * Access a property on the first matched element
		 * 
		 * @param name
		 *            attribute name
		 * @return
		 */
		public JQScriptBuilder attr(String name)
		{
			this.scriptBuilder.append(".attr('" + name + "')");
			return this;
		}

		/**
		 * Set a key/value object as properties to all matched elements.<br>
		 * This serves as the best way to set a large number of properties on all matched elements.
		 * 
		 * @param properties
		 *            attributes mapping object
		 * @return
		 */
		public JQScriptBuilder attr(JQObject properties)
		{
			this.scriptBuilder.append(".attr(" + properties + ")");
			return this;
		}

		/**
		 * Set a single property to a value, on all matched elements.
		 * 
		 * @param key
		 *            attribute name
		 * @param value
		 *            attribute value
		 * @return
		 */
		public JQScriptBuilder attr(String key, String value)
		{
			this.scriptBuilder.append(".attr('" + key + "', '" + value + "')");
			return this;
		}

		/**
		 * Set a single property to a computed value, on all matched elements.
		 * 
		 * @param key
		 *            attribute name
		 * @param fn
		 *            function which gives computed value
		 * @return
		 */
		public JQScriptBuilder attr(String key, JQFunction fn)
		{
			this.scriptBuilder.append(".attr('" + key + "', " + fn + ")");
			return this;
		}

		/**
		 * Set a single property to a computed value, on all matched elements.
		 * 
		 * @param key
		 *            attribute name
		 * @param fn
		 *            Wicket behavior. success or fail must return a computed value.
		 * @return
		 */
		public JQScriptBuilder attr(String key, AbstractDefaultJQBehavior fn)
		{
			return this.attr(key, new JQFunction(fn));
		}

		/**
		 * Remove an attribute from each of the matched elements.
		 * 
		 * @param key
		 *            attribute name
		 * @return
		 */
		public JQScriptBuilder removeAttr(String key)
		{
			this.scriptBuilder.append(".removeAttr('" + key + "')");
			return this;
		}

		/**
		 * Adds the specified class(es) to each of the set of matched elements.
		 * 
		 * @param cssClass
		 *            css class name
		 * @return
		 */
		public JQScriptBuilder addClass(String cssClass)
		{
			this.scriptBuilder.append(".addClass('" + cssClass + "')");
			return this;
		}

		/**
		 * Removes the specified class(es) from the set of matched elements.
		 * 
		 * @param cssClass
		 *            css class name
		 * @return
		 */
		public JQScriptBuilder removeClass(String cssClass)
		{
			this.scriptBuilder.append(".removeClass('" + cssClass + "')");
			return this;
		}

		/**
		 * Removes all class(es) from the set of matched elements.
		 * 
		 * @return
		 */
		public JQScriptBuilder removeClass()
		{
			this.scriptBuilder.append(".removeClass()");
			return this;
		}

		/**
		 * Adds the specified class if it is not present, removes the specified class if it is present.
		 * 
		 * @param cssClass
		 *            css class name
		 * @return
		 */
		public JQScriptBuilder toggleClass(String cssClass)
		{
			this.scriptBuilder.append(".toggleClass('" + cssClass + "')");
			return this;
		}

		/**
		 * Get the html contents (innerHTML) of the first matched element.
		 * 
		 * @return
		 */
		public JQScriptBuilder html()
		{
			this.scriptBuilder.append(".html()");
			return this;
		}

		/**
		 * Set the html contents of every matched element.
		 * 
		 * @param val
		 *            html content
		 * @return
		 */
		public JQScriptBuilder html(String val)
		{
			this.scriptBuilder.append(".html('" + val + "')");
			return this;
		}

		/**
		 * Matches all input elements of type text.
		 * 
		 * @return
		 */
		public JQScriptBuilder text()
		{
			this.scriptBuilder.append(".text()");
			return this;
		}

		/**
		 * Set the text contents of all matched elements.<br>
		 * Similar to html(), but escapes HTML (replace "<" and ">" with their HTML entities).
		 * 
		 * @param val
		 *            text content
		 * @return
		 */
		public JQScriptBuilder text(String val)
		{
			this.scriptBuilder.append(".text('" + val + "')");
			return this;
		}

		/**
		 * Get the content of the value attribute of the first matched element.
		 * 
		 * @return
		 */
		public JQScriptBuilder val()
		{
			this.scriptBuilder.append(".val()");
			return this;
		}

		/**
		 * Set the value attribute of every matched element.
		 * 
		 * @param val
		 *            value to set
		 * @return
		 */
		public JQScriptBuilder val(String val)
		{
			this.scriptBuilder.append(".text('" + val + "')");
			return this;
		}

		/**
		 * Removes all elements from the set of matched elements that do not match the specified expression(s).
		 * 
		 * @param expr
		 *            filter expression
		 * @return
		 */
		public JQScriptBuilder filter(String expr)
		{
			this.scriptBuilder.append(".filter('" + expr + "')");
			return this;
		}

		/**
		 * Removes all elements from the set of matched elements that does not match the specified function.<br>
		 * The function is called with a context equal to the current element (just like $.each.<br>
		 * If the function returns false, then the element is removed - anything else and the element is kept.
		 * 
		 * @param function
		 *            filter function
		 * @return
		 */
		public JQScriptBuilder filter(JQFunction function)
		{
			this.scriptBuilder.append(".filter(" + function + ")");
			return this;
		}

		/**
		 * Removes all elements from the set of matched elements that does not match the specified function.<br>
		 * The function is called with a context equal to the current element (just like $.each.<br>
		 * If the function returns false, then the element is removed - anything else and the element is kept.
		 * 
		 * @param function
		 *            Wicket behavior. succes or fail must filter content
		 * @return
		 */
		public JQScriptBuilder filter(AbstractDefaultJQBehavior function)
		{
			return this.filter(new JQFunction(function));
		}

		/**
		 * Checks the current selection against a class and returns true, if at least one element of the selection has the given class.<br>
		 * This is an alternative to is("." + class).
		 * 
		 * @param cssClass
		 *            css class name
		 * @return
		 */
		public JQScriptBuilder hasClass(String cssClass)
		{
			this.scriptBuilder.append(".hasClass('" + cssClass + "')");
			return this;
		}

		/**
		 * Checks the current selection against an expression and returns true, if at least one element of the selection fits the given expression.
		 * 
		 * @param expr
		 *            searched element
		 * @return
		 */
		public JQScriptBuilder is(String expr)
		{
			this.scriptBuilder.append(".is('" + expr + "')");
			return this;
		}

		/**
		 * Translate a set of elements in the jQuery object into another set of values in an array (which may, or may not, be elements).<br>
		 * You could use this to build lists of values, attributes, css values - or even perform special, custom, selector transformations.<br>
		 * 
		 * @param callback
		 *            function for translating values
		 * @return
		 */
		public JQScriptBuilder map(JQFunction callback)
		{
			this.scriptBuilder.append(".map(" + callback + ")");
			return this;
		}

		/**
		 * Translate a set of elements in the jQuery object into another set of values in an array (which may, or may not, be elements).<br>
		 * You could use this to build lists of values, attributes, css values - or even perform special, custom, selector transformations.<br>
		 * 
		 * @param callback
		 *            Wicket behavior, success or fail must translate values
		 * @return
		 */
		public JQScriptBuilder map(AbstractDefaultJQBehavior callback)
		{
			return this.map(new JQFunction(callback));
		}

		/**
		 * Removes elements matching the specified expression from the set of matched elements.
		 * 
		 * @param expr
		 *            filter expression
		 * @return
		 */
		public JQScriptBuilder not(String expr)
		{
			this.scriptBuilder.append(".not('" + expr + "')");
			return this;
		}

		/**
		 * Selects a subset of the matched elements.
		 * 
		 * @param start
		 *            slice start
		 * @param end
		 *            slice end
		 * @return
		 */
		public JQScriptBuilder slice(int start, int end)
		{
			this.scriptBuilder.append(".slice(" + start + ", " + end + ")");
			return this;
		}

		/**
		 * Adds more elements, matched by the given expression, to the set of matched elements.
		 * 
		 * @param expr
		 *            elements to add
		 * @return
		 */
		public JQScriptBuilder add(String expr)
		{
			this.scriptBuilder.append(".add('" + expr + "')");
			return this;
		}

		/**
		 * Adds more elements, matched by the given expression, to the set of matched elements.
		 * 
		 * @param element
		 *            elements to add
		 * @return
		 */
		public JQScriptBuilder add(JQDomElement element)
		{
			this.scriptBuilder.append(".add(" + element + ")");
			return this;
		}

		/**
		 * Get a set of elements containing all of the unique immediate children of each of the matched set of elements.
		 * 
		 * @return
		 */
		public JQScriptBuilder children()
		{
			this.scriptBuilder.append(".children()");
			return this;
		}

		/**
		 * Get a set of elements containing all of the unique immediate children of each of the matched set of elements.
		 * 
		 * @param expr
		 *            filter expression
		 * @return
		 */
		public JQScriptBuilder children(String expr)
		{
			this.scriptBuilder.append(".children('" + expr + "')");
			return this;
		}

		/**
		 * Find all the child nodes inside the matched elements (including text nodes), or the content document, if the element is an iframe.
		 * 
		 * @return
		 */
		public JQScriptBuilder contents()
		{
			this.scriptBuilder.append(".contents()");
			return this;
		}

		/**
		 * Searches for all elements that match the specified expression.<br>
		 * This method is a good way to find additional descendant elements with which to process.
		 * 
		 * @param expr
		 *            filter expression
		 * @return
		 */
		public JQScriptBuilder find(String expr)
		{
			this.scriptBuilder.append(".find('" + expr + "')");
			return this;
		}

		/**
		 * Get a set of elements containing the unique next siblings of each of the given set of elements.<br>
		 * next only returns the very next sibling for each element, not all next siblings (see nextAll).
		 * 
		 * @return
		 */
		public JQScriptBuilder next()
		{
			this.scriptBuilder.append(".next()");
			return this;
		}

		/**
		 * Get a set of elements containing the unique next siblings of each of the given set of elements.<br>
		 * next only returns the very next sibling for each element, not all next siblings (see nextAll).
		 * 
		 * @param expr
		 *            filtering expression
		 * @return
		 */
		public JQScriptBuilder next(String expr)
		{
			this.scriptBuilder.append(".next('" + expr + "')");
			return this;
		}

		/**
		 * Find all sibling elements after the current element.
		 * 
		 * @return
		 */
		public JQScriptBuilder nextAll()
		{
			this.scriptBuilder.append(".nextAll()");
			return this;
		}

		/**
		 * Find all sibling elements after the current element.
		 * 
		 * @param expr
		 *            filtering expression
		 * @return
		 */
		public JQScriptBuilder nextAll(String expr)
		{
			this.scriptBuilder.append(".nextAll('" + expr + "')");
			return this;
		}

		/**
		 * Get a set of elements containing the unique parents of the matched set of elements.
		 * 
		 * @return
		 */
		public JQScriptBuilder parent()
		{
			this.scriptBuilder.append(".parent()");
			return this;
		}

		/**
		 * Get a set of elements containing the unique parents of the matched set of elements.
		 * 
		 * @param expr
		 *            filter expression
		 * @return
		 */
		public JQScriptBuilder parent(String expr)
		{
			this.scriptBuilder.append(".parent('" + expr + "')");
			return this;
		}

		/**
		 * Get a set of elements containing the unique ancestors of the matched set of elements (except for the root element).
		 * 
		 * @return
		 */
		public JQScriptBuilder parents()
		{
			this.scriptBuilder.append(".parents()");
			return this;
		}

		/**
		 * Get a set of elements containing the unique ancestors of the matched set of elements (except for the root element).
		 * 
		 * @param expr
		 *            filtering expression
		 * @return
		 */
		public JQScriptBuilder parents(String expr)
		{
			this.scriptBuilder.append(".parents('" + expr + "')");
			return this;
		}

		/**
		 * Get a set of elements containing the unique previous siblings of each of the matched set of elements.
		 * 
		 * @return
		 */
		public JQScriptBuilder prev()
		{
			this.scriptBuilder.append(".prev()");
			return this;
		}

		/**
		 * Get a set of elements containing the unique previous siblings of each of the matched set of elements.
		 * 
		 * @param expr
		 *            filtering expression
		 * @return
		 */
		public JQScriptBuilder prev(String expr)
		{
			this.scriptBuilder.append(".prev('" + expr + "')");
			return this;
		}

		/**
		 * Find all sibling elements before the current element.
		 * 
		 * @return
		 */
		public JQScriptBuilder prevAll()
		{
			this.scriptBuilder.append(".prevAll()");
			return this;
		}

		/**
		 * Find all sibling elements before the current element.
		 * 
		 * @param expr
		 *            filtering expression
		 * @return
		 */
		public JQScriptBuilder prevAll(String expr)
		{
			this.scriptBuilder.append(".prevAll('" + expr + "')");
			return this;
		}

		/**
		 * Get a set of elements containing all of the unique siblings of each of the matched set of elements.
		 * 
		 * @return
		 */
		public JQScriptBuilder siblings()
		{
			this.scriptBuilder.append(".siblings()");
			return this;
		}

		/**
		 * Get a set of elements containing all of the unique siblings of each of the matched set of elements.
		 * 
		 * @param expr
		 *            filtering expression
		 * @return
		 */
		public JQScriptBuilder siblings(String expr)
		{
			this.scriptBuilder.append(".siblings('" + expr + "')");
			return this;
		}

		/**
		 * Add the previous selection to the current selection.
		 * 
		 * @return
		 */
		public JQScriptBuilder andSelf()
		{
			this.scriptBuilder.append(".andSelf()");
			return this;
		}

		/**
		 * Revert the most recent 'destructive' operation, changing the set of matched elements to its previous state (right before the destructive operation).<br>
		 * If there was no destructive operation before, an empty set is returned.<br>
		 * 
		 * @return
		 */
		public JQScriptBuilder end()
		{
			this.scriptBuilder.append(".end()");
			return this;
		}

		/**
		 * Append content to the inside of every matched element.
		 * 
		 * @param content
		 *            content to append
		 * @return
		 */
		public JQScriptBuilder append(String content)
		{
			this.scriptBuilder.append(".append('" + content + "')");
			return this;
		}

		/**
		 * Append content to the inside of every matched element.
		 * 
		 * @param element
		 *            content to append
		 * @return
		 */
		public JQScriptBuilder append(JQDomElement element)
		{
			this.scriptBuilder.append(".append(" + element + ")");
			return this;
		}

		/**
		 * Append content to the inside of every matched element.
		 * 
		 * @param jquery
		 *            content to append
		 * @return
		 */
		public JQScriptBuilder append(JQScriptBuilder jquery)
		{
			this.scriptBuilder.append(".append(" + jquery.build() + ")");
			return this;
		}

		/**
		 * Append all of the matched elements to another, specified, set of elements.
		 * 
		 * @param content
		 *            content to append
		 * @return
		 */
		public JQScriptBuilder appendTo(String content)
		{
			this.scriptBuilder.append(".appendTo('" + content + "')");
			return this;
		}

		/**
		 * Prepend content to the inside of every matched element.
		 * 
		 * @param content
		 *            content to prepend
		 * @return
		 */
		public JQScriptBuilder prepend(String content)
		{
			this.scriptBuilder.append(".prepend('" + content + "')");
			return this;
		}

		/**
		 * Prepend content to the inside of every matched element.
		 * 
		 * @param content
		 *            content to prepend
		 * @return
		 */
		public JQScriptBuilder prepend(JQDomElement content)
		{
			this.scriptBuilder.append(".prepend(" + content + ")");
			return this;
		}

		/**
		 * Prepend content to the inside of every matched element.
		 * 
		 * @param content
		 *            content to prepend
		 * @return
		 */
		public JQScriptBuilder prepend(JQScriptBuilder content)
		{
			this.scriptBuilder.append(".prepend(" + content.build() + ")");
			return this;
		}

		/**
		 * Prepend all of the matched elements to another, specified, set of elements.
		 * 
		 * @param content
		 *            content to prepend
		 * @return
		 */
		public JQScriptBuilder prependTo(String content)
		{
			this.scriptBuilder.append(".prependTo('" + content + "')");
			return this;
		}

		/**
		 * Insert content after each of the matched elements.
		 * 
		 * @param content
		 *            content to insert
		 * @return
		 */
		public JQScriptBuilder after(String content)
		{
			this.scriptBuilder.append(".after('" + content + "')");
			return this;
		}

		/**
		 * Insert content after each of the matched elements.
		 * 
		 * @param content
		 *            content to insert
		 * @return
		 */
		public JQScriptBuilder after(JQDomElement content)
		{
			this.scriptBuilder.append(".after(" + content + ")");
			return this;
		}

		/**
		 * Insert content after each of the matched elements.
		 * 
		 * @param content
		 *            content to insert
		 * @return
		 */
		public JQScriptBuilder after(JQScriptBuilder content)
		{
			this.scriptBuilder.append(".after(" + content.build() + ")");
			return this;
		}

		/**
		 * Insert content before each of the matched elements.
		 * 
		 * @param content
		 *            content to insert
		 * @return
		 */
		public JQScriptBuilder before(String content)
		{
			this.scriptBuilder.append(".before('" + content + "')");
			return this;
		}

		/**
		 * Insert content before each of the matched elements.
		 * 
		 * @param content
		 *            content to insert
		 * @return
		 */
		public JQScriptBuilder before(JQDomElement content)
		{
			this.scriptBuilder.append(".before(" + content + ")");
			return this;
		}

		/**
		 * Insert content before each of the matched elements.
		 * 
		 * @param content
		 *            content to insert
		 * @return
		 */
		public JQScriptBuilder before(JQScriptBuilder content)
		{
			this.scriptBuilder.append(".before(" + content.build() + ")");
			return this;
		}

		/**
		 * Insert all of the matched elements after another, specified, set of elements.
		 * 
		 * @param content
		 *            content to insert
		 * @return
		 */
		public JQScriptBuilder insertAfter(String content)

		{
			this.scriptBuilder.append(".insertAfter('" + content + "')");
			return this;
		}

		/**
		 * Insert all of the matched elements before another, specified, set of elements.
		 * 
		 * @param content
		 *            content to insert
		 * @return
		 */
		public JQScriptBuilder insertBefore(String content)
		{
			this.scriptBuilder.append(".insertBefore('" + content + "')");
			return this;
		}

		/**
		 * Wrap all matched elements with a structure of other elements.
		 * 
		 * @param html
		 *            content to inject
		 * @return
		 */
		public JQScriptBuilder wrap(String html)
		{
			this.scriptBuilder.append(".wrap('" + html + "')");
			return this;
		}

		/**
		 * Wrap all matched elements with a structure of other elements.
		 * 
		 * @param element
		 *            element to inject
		 * @return
		 */
		public JQScriptBuilder wrap(JQDomElement element)
		{
			this.scriptBuilder.append(".wrap(" + element + ")");
			return this;
		}

		/**
		 * Wrap all the elements in the matched set into a single wrapper element.
		 * 
		 * @param html
		 *            content to inject
		 * @return
		 */
		public JQScriptBuilder wrapAll(String html)
		{
			this.scriptBuilder.append(".wrapAll('" + html + "')");
			return this;
		}

		/**
		 * Wrap all the elements in the matched set into a single wrapper element.
		 * 
		 * @param element
		 *            element to inject
		 * @return
		 */
		public JQScriptBuilder wrapAll(JQDomElement element)
		{
			this.scriptBuilder.append(".wrapAll(" + element + ")");
			return this;
		}

		/**
		 * Wrap the inner child contents of each matched element (including text nodes) with an HTML structure.
		 * 
		 * @param html
		 *            content to inject
		 * @return
		 */
		public JQScriptBuilder wrapInner(String html)
		{
			this.scriptBuilder.append(".wrapAll('" + html + "')");
			return this;
		}

		/**
		 * Wrap the inner child contents of each matched element (including text nodes) with an HTML structure.
		 * 
		 * @param element
		 *            element to inject
		 * @return
		 */
		public JQScriptBuilder wrapInner(JQDomElement element)
		{
			this.scriptBuilder.append(".wrapAll(" + element + ")");
			return this;
		}

		/**
		 * Replaces the elements matched by the specified selector with the matched elements.
		 * 
		 * @param selector
		 *            filter selector
		 * @return
		 */
		public JQScriptBuilder replaceAll(JQSelector selector)
		{
			this.scriptBuilder.append(".replaceAll('" + selector + "')");
			return this;
		}

		/**
		 * Replaces all matched elements with the specified HTML or DOM elements.
		 * 
		 * @param content
		 *            replace content
		 * @return
		 */
		public JQScriptBuilder replaceWith(String content)
		{
			this.scriptBuilder.append(".replaceWith('" + content + "')");
			return this;
		}

		/**
		 * Replaces all matched elements with the specified HTML or DOM elements.
		 * 
		 * @param content
		 *            replace content
		 * @return
		 */
		public JQScriptBuilder replaceWith(JQDomElement content)
		{
			this.scriptBuilder.append(".replaceWith(" + content + ")");
			return this;
		}

		/**
		 * Replaces all matched elements with the specified HTML or DOM elements.
		 * 
		 * @param content
		 *            replace content
		 * @return
		 */
		public JQScriptBuilder replaceWith(JQScriptBuilder content)
		{
			this.scriptBuilder.append(".replaceWith(" + content.build() + ")");
			return this;
		}

		/**
		 * Matches all elements that have no children (including text nodes).
		 * 
		 * @return
		 */
		public JQScriptBuilder empty()
		{
			this.scriptBuilder.append(".empty()");
			return this;
		}

		/**
		 * Removes all matched elements from the DOM.<br>
		 * This does NOT remove them from the jQuery object, allowing you to use the matched elements further.<br>
		 * 
		 * @return
		 */
		public JQScriptBuilder remove()
		{
			this.scriptBuilder.append(".empty()");
			return this;
		}

		/**
		 * Removes all matched elements from the DOM.<br>
		 * This does NOT remove them from the jQuery object, allowing you to use the matched elements further.<br>
		 * 
		 * @param expr
		 *            filter expression
		 * @return
		 */
		public JQScriptBuilder remove(String expr)
		{
			this.scriptBuilder.append(".empty('" + expr + "')");
			return this;
		}

		/**
		 * Clone matched DOM Elements and select the clones.
		 * 
		 * @return
		 */
		public JQScriptBuilder clone()
		{
			this.scriptBuilder.append(".clone()");
			return this;
		}

		/**
		 * Clone matched DOM Elements, and all their event handlers, and select the clones.
		 * 
		 * @return
		 */
		public JQScriptBuilder cloneTrue()
		{
			this.scriptBuilder.append(".clone(true)");
			return this;
		}

		/**
		 * Return a style property on the first matched element.
		 * 
		 * @param name
		 *            style property name
		 * @return
		 */
		public JQScriptBuilder css(String name)
		{
			this.scriptBuilder.append(".css('" + name + "')");
			return this;
		}

		/**
		 * Set a key/value object as style properties to all matched elements.
		 * 
		 * @param properties
		 *            style properties mapping object
		 * @return
		 */
		public JQScriptBuilder css(JQObject properties)
		{
			this.scriptBuilder.append(".css(" + properties + ")");
			return this;
		}

		/**
		 * Set a single style property to a value on all matched elements.
		 * 
		 * @param name
		 *            style property name
		 * @param value
		 *            style property value
		 * @return
		 */
		public JQScriptBuilder css(String name, String value)
		{
			this.scriptBuilder.append(".css('" + name + "', '" + value + "')");
			return this;
		}

		/**
		 * Set a single style property to a value on all matched elements.
		 * 
		 * @param name
		 *            style property name
		 * @param value
		 *            style property value
		 * @return
		 */
		public JQScriptBuilder css(String name, Float value)
		{
			this.scriptBuilder.append(".css('" + name + "', " + value + ")");
			return this;
		}

		/**
		 * Get the current offset of the first matched element relative to the viewport.
		 * 
		 * @return
		 */
		public JQScriptBuilder offset()
		{
			this.scriptBuilder.append(".offset()");
			return this;
		}

		/**
		 * Get the current computed, pixel, height of the first matched element.
		 * 
		 * @return
		 */
		public JQScriptBuilder height()
		{
			this.scriptBuilder.append(".height()");
			return this;
		}

		/**
		 * Set the CSS height of every matched element.
		 * 
		 * @param val
		 *            height value
		 * @return
		 */
		public JQScriptBuilder height(String val)
		{
			this.scriptBuilder.append(".height('" + val + "')");
			return this;
		}

		/**
		 * Set the CSS height of every matched element.
		 * 
		 * @param val
		 *            height value
		 * @return
		 */
		public JQScriptBuilder height(Float val)
		{
			this.scriptBuilder.append(".height(" + val + ")");
			return this;
		}

		/**
		 * Get the current computed, pixel, width of the first matched element.
		 * 
		 * @return
		 */
		public JQScriptBuilder width()
		{
			this.scriptBuilder.append(".width()");
			return this;
		}

		/**
		 * Set the CSS width of every matched element.
		 * 
		 * @param val
		 *            width value
		 * @return
		 */
		public JQScriptBuilder width(String val)
		{
			this.scriptBuilder.append(".width('" + val + "')");
			return this;
		}

		/**
		 * Set the CSS width of every matched element.
		 * 
		 * @param val
		 *            width value
		 * @return
		 */
		public JQScriptBuilder width(Float val)
		{
			this.scriptBuilder.append(".width(" + val + ")");
			return this;
		}

		/**
		 * Binds a function to be executed whenever the DOM is ready to be traversed and manipulated.
		 * 
		 * @param fn
		 *            dom ready function
		 * @return
		 */
		public JQScriptBuilder ready(JQFunction fn)
		{
			this.scriptBuilder.append(".ready(" + fn + ")");
			return this;
		}

		/**
		 * Binds a function to be executed whenever the DOM is ready to be traversed and manipulated.
		 * 
		 * @param fn
		 *            wicket behavior
		 * @return
		 */
		public JQScriptBuilder ready(AbstractDefaultJQBehavior fn)
		{
			return this.ready(new JQFunction(fn));
		}

		/**
		 * Binds a handler to a particular event (like click) for each matched element.<br>
		 * Can also bind custom events.<br>
		 * The event handler is passed an event object that you can use to prevent default behaviour.<br>
		 * To stop both default action and event bubbling, your handler has to return false.<br>
		 * Note that this will prevent handlers on parent elements from running but not other jQuery handlers on the same element.<br>
		 * 
		 * @param type
		 *            event type
		 * @param data
		 *            optional event parameters
		 * @param fn
		 *            event function
		 * @return
		 */
		public JQScriptBuilder bind(String type, JQObject data, JQFunction fn)
		{
			this.scriptBuilder.append(".bind('" + type + "', " + data + ", " + fn + ")");
			return this;
		}

		/**
		 * Binds a handler to a particular event (like click) for each matched element.<br>
		 * Can also bind custom events.<br>
		 * The event handler is passed an event object that you can use to prevent default behaviour.<br>
		 * To stop both default action and event bubbling, your handler has to return false.<br>
		 * Note that this will prevent handlers on parent elements from running but not other jQuery handlers on the same element.<br>
		 * 
		 * @param type
		 *            event type
		 * @param data
		 *            optional event parameters
		 * @param fn
		 *            wicket behavior
		 * @return
		 */
		public JQScriptBuilder bind(String type, JQObject data, AbstractDefaultJQBehavior fn)
		{
			return this.bind(type, data, new JQFunction(fn));
		}

		/**
		 * Binds a handler to a particular event to be executed <i>once</i> for each matched element.
		 * 
		 * @param type
		 *            event type
		 * @param data
		 *            optional event parameters
		 * @param fn
		 *            event function
		 * @return
		 */
		public JQScriptBuilder one(String type, JQObject data, JQFunction fn)
		{
			this.scriptBuilder.append(".one('" + type + "', " + data + ", " + fn + ")");
			return this;
		}

		/**
		 * Binds a handler to a particular event to be executed <i>once</i> for each matched element.
		 * 
		 * @param type
		 *            event type
		 * @param data
		 *            optional event parameters
		 * @param fn
		 *            wicket behavior
		 * @return
		 */
		public JQScriptBuilder one(String type, JQObject data, AbstractDefaultJQBehavior fn)
		{
			return this.one(type, data, new JQFunction(fn));
		}

		/**
		 * Trigger a type of event on every matched element.
		 * 
		 * @param type
		 *            event type
		 * @param data
		 *            optional event parameters
		 * @return
		 */
		public JQScriptBuilder trigger(String type, JQArray data)
		{
			this.scriptBuilder.append(".trigger('" + type + "', " + data + ")");
			return this;
		}

		/**
		 * This particular method triggers all bound event handlers on an element (for a specific event type) WITHOUT executing the browsers default actions.
		 * 
		 * @param type
		 *            event type
		 * @param data
		 *            optional event parameters
		 * @return
		 */
		public JQScriptBuilder triggerHandler(String type, JQArray data)
		{
			this.scriptBuilder.append(".triggerHandler('" + type + "', " + data + ")");
			return this;
		}

		/**
		 * This does the opposite of bind, it removes bound events from each of the matched elements.
		 * 
		 * @param type
		 *            event type
		 * @param data
		 *            specific bound function to unbound
		 * @return
		 */
		public JQScriptBuilder unbind(String type, JQFunction data)
		{
			this.scriptBuilder.append(".unbind('" + type + "', " + data + ")");
			return this;
		}

		/**
		 * This does the opposite of bind, it removes bound events from each of the matched elements.
		 * 
		 * @param type
		 *            event type
		 * @param data
		 *            specific bound wicket behavior to unbound
		 * @return
		 */
		public JQScriptBuilder unbind(String type, AbstractDefaultJQBehavior data)
		{
			return this.unbind(type, new JQFunction(data));
		}

		/**
		 * Simulates hovering (moving the mouse on, and off, an object).<br>
		 * This is a custom method which provides an 'in' to a frequent task.
		 * 
		 * @param over
		 *            mouse over function
		 * @param out
		 *            mouse out function
		 * @return
		 */
		public JQScriptBuilder hover(JQFunction over, JQFunction out)
		{
			this.scriptBuilder.append(".hover(" + over + ", " + out + ")");
			return this;
		}

		/**
		 * Simulates hovering (moving the mouse on, and off, an object).<br>
		 * This is a custom method which provides an 'in' to a frequent task.
		 * 
		 * @param over
		 *            mouse over wicket behavior
		 * @param out
		 *            mouse out wicket behavior
		 * @return
		 */
		public JQScriptBuilder hover(AbstractDefaultJQBehavior over, AbstractDefaultJQBehavior out)
		{
			return this.hover(new JQFunction(over), new JQFunction(out));
		}

		/**
		 * Toggle between two function calls every other click.
		 * 
		 * @param fnOn
		 *            toggle on function
		 * @param fnOff
		 *            toggle off function
		 * @return
		 */
		public JQScriptBuilder toggle(JQFunction fnOn, JQFunction fnOff)
		{
			this.scriptBuilder.append(".toggle(" + fnOn + ", " + fnOff + ")");
			return this;
		}

		/**
		 * Toggle between two function calls every other click.
		 * 
		 * @param fnOn
		 *            toggle on wicket behavior
		 * @param fnOff
		 *            toggle off wicket behavior
		 * @return
		 */
		public JQScriptBuilder toggle(AbstractDefaultJQBehavior fnOn, AbstractDefaultJQBehavior fnOff)
		{
			return this.toggle(new JQFunction(fnOn), new JQFunction(fnOff));
		}

		/**
		 * Triggers the blur event of each matched element.<br>
		 * This causes all of the functions that have been bound to that blur event to be executed, and calls the browser's default blur action on the matching element(s).<br>
		 * This default action can be prevented by returning false from one of the functions bound to the blur event.<br>
		 * The blur event usually fires when an element loses focus either via the pointing device or by tabbing navigation
		 * 
		 * @return
		 */
		public JQScriptBuilder blur()
		{
			this.scriptBuilder.append(".blur()");
			return this;
		}

		/**
		 * Bind a function to the blur event of each matched element.
		 * 
		 * @param fn
		 *            blur function
		 * @return
		 */
		public JQScriptBuilder blur(JQFunction fn)
		{
			this.scriptBuilder.append(".blur(" + fn + ")");
			return this;
		}

		/**
		 * Bind a function to the blur event of each matched element.
		 * 
		 * @param fn
		 *            blur wicket behavior
		 * @return
		 */
		public JQScriptBuilder blur(AbstractDefaultJQBehavior fn)
		{
			return this.blur(new JQFunction(fn));
		}

		/**
		 * Triggers the change event of each matched element.<br>
		 * This causes all of the functions that have been bound to that change event to be executed, and calls the browser's default change action on the matching element(s).<br>
		 * This default action can be prevented by returning false from one of the functions bound to the change event.
		 * 
		 * @return
		 */
		public JQScriptBuilder change()
		{
			this.scriptBuilder.append(".change()");
			return this;
		}

		/**
		 * Binds a function to the change event of each matched element.
		 * 
		 * @param fn
		 *            change function
		 * @return
		 */
		public JQScriptBuilder change(JQFunction fn)
		{
			this.scriptBuilder.append(".change(" + fn + ")");
			return this;
		}

		/**
		 * Binds a function to the change event of each matched element.
		 * 
		 * @param fn
		 *            change wicket behavior
		 * @return
		 */
		public JQScriptBuilder change(AbstractDefaultJQBehavior fn)
		{
			return this.change(new JQFunction(fn));
		}

		/**
		 * Triggers the click event of each matched element.<br>
		 * Causes all of the functions that have been bound to that click event to be executed.
		 * 
		 * @return
		 */
		public JQScriptBuilder click()
		{
			this.scriptBuilder.append(".click()");
			return this;
		}

		/**
		 * Binds a function to the click event of each matched element.
		 * 
		 * @param fn
		 *            click function
		 * @return
		 */
		public JQScriptBuilder click(JQFunction fn)
		{
			this.scriptBuilder.append(".click(" + fn + ")");
			return this;
		}

		/**
		 * Binds a function to the click event of each matched element.
		 * 
		 * @param fn
		 *            click wicket behavior
		 * @return
		 */
		public JQScriptBuilder click(AbstractDefaultJQBehavior fn)
		{
			return this.click(new JQFunction(fn));
		}

		/**
		 * Triggers the dblclick event of each matched element.<br>
		 * This causes all of the functions that have been bound to that dblclick event to be executed, and calls the browser's default dblclick action on the matching element(s).<br>
		 * This default action can be prevented by returning false from one of the functions bound to the dblclick event.
		 * 
		 * @return
		 */
		public JQScriptBuilder dblclick()
		{
			this.scriptBuilder.append(".dblclick()");
			return this;
		}

		/**
		 * Binds a function to the dblclick event of each matched element.
		 * 
		 * @param fn
		 *            dblclick function
		 * @return
		 */
		public JQScriptBuilder dblclick(JQFunction fn)
		{
			this.scriptBuilder.append(".dblclick(" + fn + ")");
			return this;
		}

		/**
		 * Binds a function to the dblclick event of each matched element.
		 * 
		 * @param fn
		 *            dblclick wicket behavior
		 * @return
		 */
		public JQScriptBuilder dblclick(AbstractDefaultJQBehavior fn)
		{
			return this.dblclick(new JQFunction(fn));
		}

		/**
		 * Triggers the error event of each matched element.<br>
		 * This causes all of the functions that have been bound to that error event to be executed, and calls the browser's default error action on the matching element(s).<br>
		 * This default action can be prevented by returning false from one of the functions bound to the error event.<br>
		 * The error event usually fires when an element loses focus either via the pointing device or by tabbing navigation.
		 * 
		 * @return
		 */
		public JQScriptBuilder error()
		{
			this.scriptBuilder.append(".error()");
			return this;
		}

		/**
		 * Binds a function to the error event of each matched element.
		 * 
		 * @param fn
		 *            error function
		 * @return
		 */
		public JQScriptBuilder error(JQFunction fn)
		{
			this.scriptBuilder.append(".error(" + fn + ")");
			return this;
		}

		/**
		 * Binds a function to the error event of each matched element.
		 * 
		 * @param fn
		 *            error wicket behavior
		 * @return
		 */
		public JQScriptBuilder error(AbstractDefaultJQBehavior fn)
		{
			return this.error(new JQFunction(fn));
		}

		/**
		 * Triggers the focus event of each matched element. <br>
		 * This causes all of the functions that have been bound to the focus event to be executed.<br>
		 * Note that this does not execute the focus method of the underlying elements.
		 * 
		 * @return
		 */
		public JQScriptBuilder focus()
		{
			this.scriptBuilder.append(".focus()");
			return this;
		}

		/**
		 * Binds a function to the focus event of each matched element.
		 * 
		 * @param fn
		 *            focus function
		 * @return
		 */
		public JQScriptBuilder focus(JQFunction fn)
		{
			this.scriptBuilder.append(".focus(" + fn + ")");
			return this;
		}

		/**
		 * Binds a function to the focus event of each matched element.
		 * 
		 * @param fn
		 *            focus wicket behavior
		 * @return
		 */
		public JQScriptBuilder focus(AbstractDefaultJQBehavior fn)
		{
			return this.focus(new JQFunction(fn));
		}

		/**
		 * Triggers the keydown event of each matched element.<br>
		 * This causes all of the functions that have been bound to the keydown event to be executed, and calls the browser's default keydown action on the matching element(s).<br>
		 * This default action can be prevented by returning false from one of the functions bound to the keydown event.
		 * 
		 * @return
		 */
		public JQScriptBuilder keydown()
		{
			this.scriptBuilder.append(".keydown()");
			return this;
		}

		/**
		 * Bind a function to the keydown event of each matched element.
		 * 
		 * @param fn
		 *            keydown function
		 * @return
		 */
		public JQScriptBuilder keydown(JQFunction fn)
		{
			this.scriptBuilder.append(".keydown(" + fn + ")");
			return this;
		}

		/**
		 * Bind a function to the keydown event of each matched element.
		 * 
		 * @param fn
		 *            keydown wicket behavior
		 * @return
		 */
		public JQScriptBuilder keydown(AbstractDefaultJQBehavior fn)
		{
			return this.keydown(new JQFunction(fn));
		}

		/**
		 * Triggers the keypress event of each matched element.<br>
		 * This causes all of the functions that have been bound to the keypress event to be executed, and calls the browser's default keypress action on the matching element(s).<br>
		 * This default action can be prevented by returning false from one of the functions bound to the keypress event.
		 * 
		 * @return
		 */
		public JQScriptBuilder keypress()
		{
			this.scriptBuilder.append(".keypress()");
			return this;
		}

		/**
		 * Binds a function to the keypress event of each matched element.
		 * 
		 * @param fn
		 *            keypress function
		 * @return
		 */
		public JQScriptBuilder keypress(JQFunction fn)
		{
			this.scriptBuilder.append(".keypress(" + fn + ")");
			return this;
		}

		/**
		 * Binds a function to the keypress event of each matched element.
		 * 
		 * @param fn
		 *            keypress wicket behavior
		 * @return
		 */
		public JQScriptBuilder keypress(AbstractDefaultJQBehavior fn)
		{
			return this.keypress(new JQFunction(fn));
		}

		/**
		 * Triggers the keyup event of each matched element.<br>
		 * This causes all of the functions that have been bound to the keyup event to be executed, and calls the browser's default keyup action on the matching element(s).<br>
		 * This default action can be prevented by returning false from one of the functions bound to the keyup event.
		 * 
		 * @return
		 */
		public JQScriptBuilder keyup()
		{
			this.scriptBuilder.append(".keyup()");
			return this;
		}

		/**
		 * Bind a function to the keyup event of each matched element.
		 * 
		 * @param fn
		 *            keyup function
		 * @return
		 */
		public JQScriptBuilder keyup(JQFunction fn)
		{
			this.scriptBuilder.append(".keyup(" + fn + ")");
			return this;
		}

		/**
		 * Bind a function to the keyup event of each matched element.
		 * 
		 * @param fn
		 *            keyup wicket behavior
		 * @return
		 */
		public JQScriptBuilder keyup(AbstractDefaultJQBehavior fn)
		{
			return this.keyup(new JQFunction(fn));
		}

		/**
		 * Binds a function to the load event of each matched element.<br>
		 * When bound to the window element, the event fires when the user agent finishes loading all content within a document, including window, frames, objects and images.<br>
		 * For elements, it fires when the target element and all of its content has finished loading.
		 * 
		 * @param fn
		 *            load function
		 * @return
		 */
		public JQScriptBuilder load(JQFunction fn)
		{
			this.scriptBuilder.append(".load(" + fn + ")");
			return this;
		}

		/**
		 * Binds a function to the load event of each matched element.<br>
		 * When bound to the window element, the event fires when the user agent finishes loading all content within a document, including window, frames, objects and images.<br>
		 * For elements, it fires when the target element and all of its content has finished loading.
		 * 
		 * @param fn
		 *            load wicket behavior
		 * @return
		 */
		public JQScriptBuilder load(AbstractDefaultJQBehavior fn)
		{
			return this.load(new JQFunction(fn));
		}

		/**
		 * Binds a function to the mousedown event of each matched element.
		 * 
		 * @param fn
		 *            mousedown function
		 * @return
		 */
		public JQScriptBuilder mousedown(JQFunction fn)
		{
			this.scriptBuilder.append(".mousedown(" + fn + ")");
			return this;
		}

		/**
		 * Binds a function to the mousedown event of each matched element.
		 * 
		 * @param fn
		 *            mousedown wicket behavior
		 * @return
		 */
		public JQScriptBuilder mousedown(AbstractDefaultJQBehavior fn)
		{
			return this.mousedown(new JQFunction(fn));
		}

		/**
		 * Bind a function to the mousemove event of each matched element.
		 * 
		 * @param fn
		 *            mousemove function
		 * @return
		 */
		public JQScriptBuilder mousemove(JQFunction fn)
		{
			this.scriptBuilder.append(".mousemove(" + fn + ")");
			return this;
		}

		/**
		 * Bind a function to the mousemove event of each matched element.
		 * 
		 * @param fn
		 *            mousemove wicket behavior
		 * @return
		 */
		public JQScriptBuilder mousemove(AbstractDefaultJQBehavior fn)
		{
			return this.mousedown(new JQFunction(fn));
		}

		/**
		 * Bind a function to the mouseout event of each matched element.
		 * 
		 * @param fn
		 *            mouseout function
		 * @return
		 */
		public JQScriptBuilder mouseout(JQFunction fn)
		{
			this.scriptBuilder.append(".mouseout(" + fn + ")");
			return this;
		}

		/**
		 * Bind a function to the mouseout event of each matched element.
		 * 
		 * @param fn
		 *            mouseout wicket behavior
		 * @return
		 */
		public JQScriptBuilder mouseout(AbstractDefaultJQBehavior fn)
		{
			return this.mouseout(new JQFunction(fn));
		}

		/**
		 * Bind a function to the mouseover event of each matched element.
		 * 
		 * @param fn
		 *            mouseover function
		 * @return
		 */
		public JQScriptBuilder mouseover(JQFunction fn)
		{
			this.scriptBuilder.append(".mouseover(" + fn + ")");
			return this;
		}

		/**
		 * Bind a function to the mouseover event of each matched element.
		 * 
		 * @param fn
		 *            mouseover wicket behavior
		 * @return
		 */
		public JQScriptBuilder mouseover(AbstractDefaultJQBehavior fn)
		{
			return this.mouseover(new JQFunction(fn));
		}

		/**
		 * Bind a function to the mouseup event of each matched element.
		 * 
		 * @param fn
		 *            mouseup function
		 * @return
		 */
		public JQScriptBuilder mouseup(JQFunction fn)
		{
			this.scriptBuilder.append(".mouseup(" + fn + ")");
			return this;
		}

		/**
		 * Bind a function to the mouseup event of each matched element.
		 * 
		 * @param fn
		 *            mouseup wicket behavior
		 * @return
		 */
		public JQScriptBuilder mouseup(AbstractDefaultJQBehavior fn)
		{
			return this.mouseup(new JQFunction(fn));
		}

		/**
		 * Bind a function to the resize event of each matched element.
		 * 
		 * @param fn
		 *            resize function
		 * @return
		 */
		public JQScriptBuilder resize(JQFunction fn)
		{
			this.scriptBuilder.append(".resize(" + fn + ")");
			return this;
		}

		/**
		 * Bind a function to the resize event of each matched element.
		 * 
		 * @param fn
		 *            resize wicket behavior
		 * @return
		 */
		public JQScriptBuilder resize(AbstractDefaultJQBehavior fn)
		{
			return this.resize(new JQFunction(fn));
		}

		/**
		 * Bind a function to the scroll event of each matched element.
		 * 
		 * @param fn
		 *            scroll function
		 * @return
		 */
		public JQScriptBuilder scroll(JQFunction fn)
		{
			this.scriptBuilder.append(".scroll(" + fn + ")");
			return this;
		}

		/**
		 * Bind a function to the scroll event of each matched element.
		 * 
		 * @param fn
		 *            scroll function
		 * @return
		 */
		public JQScriptBuilder scroll(AbstractDefaultJQBehavior fn)
		{
			return this.scroll(new JQFunction(fn));
		}

		/**
		 * Trigger the select event of each matched element.<br>
		 * This causes all of the functions that have been bound to that select event to be executed, and calls the browser's default select action on the matching element(s).<br>
		 * This default action can be prevented by returning false from one of the functions bound to the select event.
		 * 
		 * @return
		 */
		public JQScriptBuilder select()
		{
			this.scriptBuilder.append(".select()");
			return this;
		}

		/**
		 * Bind a function to the select event of each matched element.
		 * 
		 * @param fn
		 *            select function
		 * @return
		 */
		public JQScriptBuilder select(JQFunction fn)
		{
			this.scriptBuilder.append(".select(" + fn + ")");
			return this;
		}

		/**
		 * Bind a function to the select event of each matched element.
		 * 
		 * @param fn
		 *            select wicket behavior
		 * @return
		 */
		public JQScriptBuilder select(AbstractDefaultJQBehavior fn)
		{
			return this.select(fn);
		}

		/**
		 * Matches all input elements of type submit.
		 * 
		 * @return
		 */
		public JQScriptBuilder submit()
		{
			this.scriptBuilder.append(".submit()");
			return this;
		}

		/**
		 * Bind a function to the submit event of each matched element.
		 * 
		 * @param fn
		 *            submit function
		 * @return
		 */
		public JQScriptBuilder submit(JQFunction fn)
		{
			this.scriptBuilder.append(".submit(" + fn + ")");
			return this;
		}

		/**
		 * Bind a function to the submit event of each matched element.
		 * 
		 * @param fn
		 *            submit wicket behavior
		 * @return
		 */
		public JQScriptBuilder submit(AbstractDefaultJQBehavior fn)
		{
			return this.submit(new JQFunction(fn));
		}

		/**
		 * Binds a function to the unload event of each matched element.
		 * 
		 * @param fn
		 *            unload function
		 * @return
		 */
		public JQScriptBuilder unload(JQFunction fn)
		{
			this.scriptBuilder.append(".unload(" + fn + ")");
			return this;
		}

		/**
		 * Binds a function to the unload event of each matched element.
		 * 
		 * @param fn
		 *            unload wicket behavior
		 * @return
		 */
		public JQScriptBuilder unload(AbstractDefaultJQBehavior fn)
		{
			return this.unload(new JQFunction(fn));
		}

		/**
		 * Hides each of the set of matched elements if they are shown.
		 * 
		 * @return
		 */
		public JQScriptBuilder hide()
		{
			this.scriptBuilder.append(".hide()");
			return this;
		}

		/**
		 * Hide all matched elements using a graceful animation and firing an optional callback after completion.<br>
		 * The height, width, and opacity of each of the matched elements are changed dynamically according to the specified speed.
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback function
		 * @return
		 */
		public JQScriptBuilder hide(String speed, JQFunction callback)
		{
			this.scriptBuilder.append(".hide('" + speed + "', " + callback + ")");
			return this;
		}

		/**
		 * Hide all matched elements using a graceful animation and firing an optional callback after completion.<br>
		 * The height, width, and opacity of each of the matched elements are changed dynamically according to the specified speed.
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback wicket behavior
		 * @return
		 */
		public JQScriptBuilder hide(String speed, AbstractDefaultJQBehavior callback)
		{
			return this.hide(speed, new JQFunction(callback));
		}

		/**
		 * Hide all matched elements using a graceful animation and firing an optional callback after completion.<br>
		 * The height, width, and opacity of each of the matched elements are changed dynamically according to the specified speed.
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback function
		 * @return
		 */
		public JQScriptBuilder hide(Float speed, JQFunction callback)
		{
			this.scriptBuilder.append(".hide(" + speed + ", " + callback + ")");
			return this;
		}

		/**
		 * Hide all matched elements using a graceful animation and firing an optional callback after completion.<br>
		 * The height, width, and opacity of each of the matched elements are changed dynamically according to the specified speed.
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback wicket behavior
		 * @return
		 */
		public JQScriptBuilder hide(Float speed, AbstractDefaultJQBehavior callback)
		{
			return this.hide(speed, new JQFunction(callback));
		}

		/**
		 * Displays each of the set of matched elements if they are hidden.
		 * 
		 * @return
		 */
		public JQScriptBuilder show()
		{
			this.scriptBuilder.append(".show()");
			return this;
		}

		/**
		 * Show all matched elements using a graceful animation and firing an optional callback after completion.<br>
		 * The height, width, and opacity of each of the matched elements are changed dynamically according to the specified speed.<br>
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback function
		 * @return
		 */
		public JQScriptBuilder show(String speed, JQFunction callback)
		{
			this.scriptBuilder.append(".show('" + speed + "', " + callback + ")");
			return this;
		}

		/**
		 * Show all matched elements using a graceful animation and firing an optional callback after completion.<br>
		 * The height, width, and opacity of each of the matched elements are changed dynamically according to the specified speed.<br>
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback wicket behavior
		 * @return
		 */
		public JQScriptBuilder show(String speed, AbstractDefaultJQBehavior callback)
		{
			return this.show(speed, new JQFunction(callback));
		}

		/**
		 * Show all matched elements using a graceful animation and firing an optional callback after completion.<br>
		 * The height, width, and opacity of each of the matched elements are changed dynamically according to the specified speed.<br>
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback function
		 * @return
		 */
		public JQScriptBuilder show(Float speed, JQFunction callback)
		{
			this.scriptBuilder.append(".show(" + speed + ", " + callback + ")");
			return this;
		}

		/**
		 * Show all matched elements using a graceful animation and firing an optional callback after completion.<br>
		 * The height, width, and opacity of each of the matched elements are changed dynamically according to the specified speed.<br>
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback wicket behavior
		 * @return
		 */
		public JQScriptBuilder show(Float speed, AbstractDefaultJQBehavior callback)
		{
			return this.show(speed, new JQFunction(callback));
		}

		/**
		 * Toggles each of the set of matched elements.<br>
		 * If they are shown, toggle makes them hidden. If they are hidden, toggle makes them shown.
		 * 
		 * @return
		 */
		public JQScriptBuilder toggle()
		{
			this.scriptBuilder.append(".toggle()");
			return this;
		}

		/**
		 * Reveal all matched elements by adjusting their height and firing an optional callback after completion.<br>
		 * Only the height is adjusted for this animation, causing all matched elements to be revealed in a "sliding" manner.
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback function
		 * @return
		 */
		public JQScriptBuilder slideDown(String speed, JQFunction callback)
		{
			this.scriptBuilder.append(".slideDown('" + speed + "', " + callback + ")");
			return this;
		}

		/**
		 * Reveal all matched elements by adjusting their height and firing an optional callback after completion.<br>
		 * Only the height is adjusted for this animation, causing all matched elements to be revealed in a "sliding" manner.
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback wicket behavior
		 * @return
		 */
		public JQScriptBuilder slideDown(String speed, AbstractDefaultJQBehavior callback)
		{
			return this.slideDown(speed, new JQFunction(callback));
		}

		/**
		 * Reveal all matched elements by adjusting their height and firing an optional callback after completion.<br>
		 * Only the height is adjusted for this animation, causing all matched elements to be revealed in a "sliding" manner.
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback function
		 * @return
		 */
		public JQScriptBuilder slideDown(Float speed, JQFunction callback)
		{
			this.scriptBuilder.append(".slideDown(" + speed + ", " + callback + ")");
			return this;
		}

		/**
		 * Reveal all matched elements by adjusting their height and firing an optional callback after completion.<br>
		 * Only the height is adjusted for this animation, causing all matched elements to be revealed in a "sliding" manner.
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback wicket behavior
		 * @return
		 */
		public JQScriptBuilder slideDown(Float speed, AbstractDefaultJQBehavior callback)
		{
			return this.slideDown(speed, new JQFunction(callback));
		}

		/**
		 * Toggle the visibility of all matched elements by adjusting their height and firing an optional callback after completion.<br>
		 * Only the height is adjusted for this animation, causing all matched elements to be hidden or shown in a "sliding" manner.
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback function
		 * @return
		 */
		public JQScriptBuilder slideToggle(String speed, JQFunction callback)
		{
			this.scriptBuilder.append(".slideToggle('" + speed + "', " + callback + ")");
			return this;
		}

		/**
		 * Toggle the visibility of all matched elements by adjusting their height and firing an optional callback after completion.<br>
		 * Only the height is adjusted for this animation, causing all matched elements to be hidden or shown in a "sliding" manner.
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback wicket behavior
		 * @return
		 */
		public JQScriptBuilder slideToggle(String speed, AbstractDefaultJQBehavior callback)
		{
			return this.slideToggle(speed, new JQFunction(callback));
		}

		/**
		 * Toggle the visibility of all matched elements by adjusting their height and firing an optional callback after completion.<br>
		 * Only the height is adjusted for this animation, causing all matched elements to be hidden or shown in a "sliding" manner.
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback function
		 * @return
		 */
		public JQScriptBuilder slideToggle(Float speed, JQFunction callback)
		{
			this.scriptBuilder.append(".slideToggle(" + speed + ", " + callback + ")");
			return this;
		}

		/**
		 * Toggle the visibility of all matched elements by adjusting their height and firing an optional callback after completion.<br>
		 * Only the height is adjusted for this animation, causing all matched elements to be hidden or shown in a "sliding" manner.
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback wicket behavior
		 * @return
		 */
		public JQScriptBuilder slideToggle(Float speed, AbstractDefaultJQBehavior callback)
		{
			return this.slideToggle(speed, new JQFunction(callback));
		}

		/**
		 * Hide all matched elements by adjusting their height and firing an optional callback after completion.<br>
		 * Only the height is adjusted for this animation, causing all matched elements to be hidden in a "sliding" manner.
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback function
		 * @return
		 */
		public JQScriptBuilder slideUp(String speed, JQFunction callback)
		{
			this.scriptBuilder.append(".slideUp('" + speed + "', " + callback + ")");
			return this;
		}

		/**
		 * Hide all matched elements by adjusting their height and firing an optional callback after completion.<br>
		 * Only the height is adjusted for this animation, causing all matched elements to be hidden in a "sliding" manner.
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback wicket behavior
		 * @return
		 */
		public JQScriptBuilder slideUp(String speed, AbstractDefaultJQBehavior callback)
		{
			return this.slideUp(speed, new JQFunction(callback));
		}

		/**
		 * Hide all matched elements by adjusting their height and firing an optional callback after completion.<br>
		 * Only the height is adjusted for this animation, causing all matched elements to be hidden in a "sliding" manner.
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback function
		 * @return
		 */
		public JQScriptBuilder slideUp(Float speed, JQFunction callback)
		{
			this.scriptBuilder.append(".slideUp(" + speed + ", " + callback + ")");
			return this;
		}

		/**
		 * Hide all matched elements by adjusting their height and firing an optional callback after completion.<br>
		 * Only the height is adjusted for this animation, causing all matched elements to be hidden in a "sliding" manner.
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback wicket behavior
		 * @return
		 */
		public JQScriptBuilder slideUp(Float speed, AbstractDefaultJQBehavior callback)
		{
			return this.slideUp(speed, new JQFunction(callback));
		}

		/**
		 * Fade in all matched elements by adjusting their opacity and firing an optional callback after completion.<br>
		 * Only the opacity is adjusted for this animation, meaning that all of the matched elements should already have some form of height and width associated with them.
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback function
		 * @return
		 */
		public JQScriptBuilder fadeIn(String speed, JQFunction callback)
		{
			this.scriptBuilder.append(".fadeIn('" + speed + "', " + callback + ")");
			return this;
		}

		/**
		 * Fade in all matched elements by adjusting their opacity and firing an optional callback after completion.<br>
		 * Only the opacity is adjusted for this animation, meaning that all of the matched elements should already have some form of height and width associated with them.
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback wicket behavior
		 * @return
		 */
		public JQScriptBuilder fadeIn(String speed, AbstractDefaultJQBehavior callback)
		{
			return this.fadeIn(speed, new JQFunction(callback));
		}

		/**
		 * Fade in all matched elements by adjusting their opacity and firing an optional callback after completion.<br>
		 * Only the opacity is adjusted for this animation, meaning that all of the matched elements should already have some form of height and width associated with them.
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback function
		 * @return
		 */
		public JQScriptBuilder fadeIn(Float speed, JQFunction callback)
		{
			this.scriptBuilder.append(".fadeIn(" + speed + ", " + callback + ")");
			return this;
		}

		/**
		 * Fade in all matched elements by adjusting their opacity and firing an optional callback after completion.<br>
		 * Only the opacity is adjusted for this animation, meaning that all of the matched elements should already have some form of height and width associated with them.
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback wicket behavior
		 * @return
		 */
		public JQScriptBuilder fadeIn(Float speed, AbstractDefaultJQBehavior callback)
		{
			return this.fadeIn(speed, new JQFunction(callback));
		}

		/**
		 * Fade out all matched elements by adjusting their opacity and firing an optional callback after completion.<br>
		 * Only the opacity is adjusted for this animation, meaning that all of the matched elements should already have some form of height and width associated with them.<br>
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback function
		 * @return
		 */
		public JQScriptBuilder fadeOut(String speed, JQFunction callback)
		{
			this.scriptBuilder.append(".fadeOut('" + speed + "', " + callback + ")");
			return this;
		}

		/**
		 * Fade out all matched elements by adjusting their opacity and firing an optional callback after completion.<br>
		 * Only the opacity is adjusted for this animation, meaning that all of the matched elements should already have some form of height and width associated with them.<br>
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback wicket behavior
		 * @return
		 */
		public JQScriptBuilder fadeOut(String speed, AbstractDefaultJQBehavior callback)
		{
			return this.fadeOut(speed, new JQFunction(callback));
		}

		/**
		 * Fade out all matched elements by adjusting their opacity and firing an optional callback after completion.<br>
		 * Only the opacity is adjusted for this animation, meaning that all of the matched elements should already have some form of height and width associated with them.<br>
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback wicket function
		 * @return
		 */
		public JQScriptBuilder fadeOut(Float speed, JQFunction callback)
		{
			this.scriptBuilder.append(".fadeOut(" + speed + ", " + callback + ")");
			return this;
		}

		/**
		 * Fade out all matched elements by adjusting their opacity and firing an optional callback after completion.<br>
		 * Only the opacity is adjusted for this animation, meaning that all of the matched elements should already have some form of height and width associated with them.<br>
		 * 
		 * @param speed
		 *            animation speed
		 * @param callback
		 *            callback wicket behavior
		 * @return
		 */
		public JQScriptBuilder fadeOut(Float speed, AbstractDefaultJQBehavior callback)
		{
			return this.fadeOut(speed, new JQFunction(callback));
		}

		/**
		 * Fade out all matched elements by adjusting their opacity and firing an optional callback after completion.<br>
		 * Only the opacity is adjusted for this animation, meaning that all of the matched elements should already have some form of height and width associated with them.<br>
		 * 
		 * @param speed
		 *            animation speed
		 * @param opacity
		 *            fade opacity
		 * @param callback
		 *            callback function
		 * @return
		 */
		public JQScriptBuilder fadeTo(String speed, Float opacity, JQFunction callback)
		{
			this.scriptBuilder.append(".fadeTo('" + speed + "', " + opacity + ", " + callback + ")");
			return this;
		}

		/**
		 * Fade out all matched elements by adjusting their opacity and firing an optional callback after completion.<br>
		 * Only the opacity is adjusted for this animation, meaning that all of the matched elements should already have some form of height and width associated with them.<br>
		 * 
		 * @param speed
		 *            animation speed
		 * @param opacity
		 *            fade opacity
		 * @param callback
		 *            callback wicket behavior
		 * @return
		 */
		public JQScriptBuilder fadeTo(String speed, Float opacity, AbstractDefaultJQBehavior callback)
		{
			return this.fadeTo(speed, opacity, new JQFunction(callback));
		}

		/**
		 * Fade out all matched elements by adjusting their opacity and firing an optional callback after completion.<br>
		 * Only the opacity is adjusted for this animation, meaning that all of the matched elements should already have some form of height and width associated with them.<br>
		 * 
		 * @param speed
		 *            animation speed
		 * @param opacity
		 *            fade opacity
		 * @param callback
		 *            callback function
		 * @return
		 */
		public JQScriptBuilder fadeTo(Float speed, Float opacity, JQFunction callback)
		{
			this.scriptBuilder.append(".fadeTo(" + speed + "', " + opacity + ", " + callback + ")");
			return this;
		}

		/**
		 * Fade out all matched elements by adjusting their opacity and firing an optional callback after completion.<br>
		 * Only the opacity is adjusted for this animation, meaning that all of the matched elements should already have some form of height and width associated with them.<br>
		 * 
		 * @param speed
		 *            animation speed
		 * @param opacity
		 *            fade opacity
		 * @param callback
		 *            callback wicket behaviors
		 * @return
		 */
		public JQScriptBuilder fadeTo(Float speed, Float opacity, AbstractDefaultJQBehavior callback)
		{
			return this.fadeTo(speed, opacity, new JQFunction(callback));
		}

		// TODO CUSTOM ANIMATION SUPPORT EASING PLUGIN REQUIRED
		// public JQScriptBuilder animate()
		// {
		// return this;
		// }
		//
		// public JQScriptBuilder dequeue()
		// {
		// this.scriptBuilder.append(".dequeue()");
		// return this;
		// }
		//
		// public JQScriptBuilder queue()
		// {
		// this.scriptBuilder.append(".queue()");
		// return this;
		// }
		//
		// public JQScriptBuilder queue(JQFunction callback)
		// {
		// this.scriptBuilder.append(".queue(" + callback + ")");
		// return this;
		// }
		//
		// public JQScriptBuilder queue(AbstractDefaultJQBehavior callback)
		// {
		// return this.queue(new JQFunction(callback));
		// }
		//
		// public JQScriptBuilder queue(JQFunction[] callback)
		// {
		// this.scriptBuilder.append(".queue(" + callback + ")");
		// return this;
		// }
		//
		// public JQScriptBuilder stop()
		// {
		// this.scriptBuilder.append(".stop()");
		// return this;
		// }

		/**
		 * Load a remote page using an HTTP request.<br>
		 * This is jQuery's low-level AJAX implementation.<br>
		 * See $.get, $.post etc. for higher-level abstractions that are often easier to understand and use, but don't offer as much functionality (such as error callbacks).<br>
		 * <p>
		 * Warning: All POST are converted to GET when 'script' is the dataType.(because it loads script as a dom script tag)
		 * </p>
		 * $.ajax() returns the XMLHttpRequest that it creates. In most cases you won't need that object to manipulate directly, but it is available if you need to abort the request manually.<br>
		 * <p>
		 * Note: If you specify the dataType option described below, make sure the server sends the correct MIME type in the response (eg. xml as "text/xml"). <br>
		 * Sending the wrong MIME type can lead to unexpected problems in your script.<br>
		 * See <a href='Specifying_the_Data_Type_for_AJAX_Requests'>Specifying the Data Type for AJAX Requests</a> for more information.
		 * </p>
		 * $.ajax() takes one argument, an object of key/value pairs, that are used to initialize and handle the request. <br>
		 * See below for a full list of the key/values that can be used.
		 * <p>
		 * As of jQuery 1.2, you can load JSON data located on another domain if you specify a <a href="http://bob.pythonmac.org/archives/2005/12/05/remote-json-jsonp/JSONP">callback</a>, which can be done like so: "myurl?callback=?". <br>
		 * jQuery automatically replaces the ? with the correct method name to call, calling your specified callback. <br>
		 * Or, if you set the dataType to "jsonp" a callback will be automatically added to your Ajax request.
		 * </p>
		 * 
		 * @param options
		 *            ajax options
		 */
		public void ajax(JQAjaxOptions options)
		{
			this.scriptBuilder.append(".ajax(" + options + ")");
		}

		/**
		 * Load a remote page using an HTTP GET request.<br>
		 * This is an easy way to send a simple GET request to a server without having to use the more complex $.ajax function.<br>
		 * It allows a single callback function to be specified that will be executed when the request is complete (and only if the response has a successful response code).<br>
		 * If you need to have both error and success callbacks, you may want to use $.ajax.
		 * 
		 * @param url
		 *            requested url
		 * @param data
		 *            request parameters
		 * @param callback
		 *            callback function
		 */
		public void get(String url, JQObject data, JQFunction callback)
		{
			this.scriptBuilder.append(".get('" + url + "', " + data + ", " + callback + ")");
		}

		/**
		 * Load a remote page using an HTTP GET request.<br>
		 * This is an easy way to send a simple GET request to a server without having to use the more complex $.ajax function.<br>
		 * It allows a single callback function to be specified that will be executed when the request is complete (and only if the response has a successful response code).<br>
		 * If you need to have both error and success callbacks, you may want to use $.ajax.
		 * 
		 * @param url
		 *            requested url
		 * @param data
		 *            request parameters
		 * @param callback
		 *            callback wicket behavior
		 */
		public void get(String url, JQObject data, AbstractDefaultJQBehavior callback)
		{
			this.get(url, data, new JQFunction(callback));
		}

		/**
		 * Load JSON data using an HTTP GET request.<br>
		 * As of jQuery 1.2, you can load JSON data located on another domain if you specify a <a href="http://bob.pythonmac.org/archives/2005/12/05/remote-json-jsonp/JSONP">callback</a>, which can be done like so: "myurl?callback=?". <br>
		 * jQuery automatically replaces the ? with the correct method name to call, calling your specified callback.
		 * 
		 * @param url
		 *            requested url
		 * @param data
		 *            request parameters
		 * @param callback
		 *            callback function
		 */
		public void getJSON(String url, JQObject data, JQFunction callback)
		{
			this.scriptBuilder.append(".getJSON('" + url + "', " + data + ", " + callback + ")");
		}

		/**
		 * Load JSON data using an HTTP GET request.<br>
		 * As of jQuery 1.2, you can load JSON data located on another domain if you specify a <a href="http://bob.pythonmac.org/archives/2005/12/05/remote-json-jsonp/JSONP">callback</a>, which can be done like so: "myurl?callback=?". <br>
		 * jQuery automatically replaces the ? with the correct method name to call, calling your specified callback.
		 * 
		 * @param url
		 *            requested url
		 * @param data
		 *            request parameters
		 * @param callback
		 *            callback wicket behavior
		 */
		public void getJSON(String url, JQObject data, AbstractDefaultJQBehavior callback)
		{
			this.getJSON(url, data, new JQFunction(callback));
		}

		/**
		 * Loads, and executes, a local JavaScript file using an HTTP GET request.
		 * 
		 * @param url
		 *            requested url
		 * @param callback
		 *            callback function
		 */
		public void getScript(String url, JQFunction callback)
		{
			this.scriptBuilder.append(".getJSON('" + url + "', " + callback + ")");
		}

		/**
		 * Loads, and executes, a local JavaScript file using an HTTP GET request.
		 * 
		 * @param url
		 *            requested url
		 * @param callback
		 *            callback wicket behavior
		 */
		public void getScript(String url, AbstractDefaultJQBehavior callback)
		{
			this.getScript(url, new JQFunction(callback));
		}

		/**
		 * Load a remote page using an HTTP POST request.<br>
		 * This is an easy way to send a simple POST request to a server without having to use the more complex $.ajax function.<br>
		 * It allows a single callback function to be specified that will be executed when the request is complete (and only if the response has a successful response code).<br>
		 * If you need to have both error and success callbacks, you may want to use $.ajax.
		 * 
		 * @param url
		 *            requested url
		 * @param data
		 *            request parameters
		 * @param callback
		 *            callback function
		 */
		public void post(String url, JQObject data, JQFunction callback)
		{
			this.scriptBuilder.append(".post('" + url + "', " + data + ", " + callback + ")");
		}

		/**
		 * Load a remote page using an HTTP POST request.<br>
		 * This is an easy way to send a simple POST request to a server without having to use the more complex $.ajax function.<br>
		 * It allows a single callback function to be specified that will be executed when the request is complete (and only if the response has a successful response code).<br>
		 * If you need to have both error and success callbacks, you may want to use $.ajax.
		 * 
		 * @param url
		 *            requested url
		 * @param data
		 *            request parameters
		 * @param callback
		 *            callback wicket behavior
		 */
		public void post(String url, JQObject data, AbstractDefaultJQBehavior callback)
		{
			this.post(url, data, new JQFunction(callback));
		}

		/**
		 * Load HTML from a remote file and inject it into the DOM.<br>
		 * A GET request will be performed by default - but if you pass in any extra parameters then a POST will occur.
		 * 
		 * @param url
		 *            requested url
		 * @param data
		 *            request parameters
		 * @param callback
		 *            callback function
		 * @return
		 */
		public JQScriptBuilder load(String url, JQObject data, JQFunction callback)
		{
			this.scriptBuilder.append(".load('" + url + "', " + data + ", " + callback + ")");
			return this;
		}

		/**
		 * Load HTML from a remote file and inject it into the DOM.<br>
		 * A GET request will be performed by default - but if you pass in any extra parameters then a POST will occur.
		 * 
		 * @param url
		 *            requested url
		 * @param data
		 *            request parameters
		 * @param callback
		 *            callback wicket behavior
		 * @return
		 */
		public JQScriptBuilder load(String url, JQObject data, AbstractDefaultJQBehavior callback)
		{
			return this.load(url, data, new JQFunction(callback));
		}

		/**
		 * Attach a function to be executed whenever an AJAX request completes.
		 * 
		 * @param callback
		 *            callback function
		 * @return
		 */
		public JQScriptBuilder ajaxComplete(JQFunction callback)
		{
			this.scriptBuilder.append(".ajaxComplete(" + callback + ")");
			return this;
		}

		/**
		 * Attach a function to be executed whenever an AJAX request completes.
		 * 
		 * @param callback
		 *            callback wicket behavior
		 * @return
		 */
		public JQScriptBuilder ajaxComplete(AbstractDefaultJQBehavior callback)
		{
			return this.ajaxComplete(new JQFunction(callback));
		}

		/**
		 * Attach a function to be executed whenever an AJAX request fails.
		 * 
		 * @param callback
		 *            callback function
		 * @return
		 */
		public JQScriptBuilder ajaxError(JQFunction callback)
		{
			this.scriptBuilder.append(".ajaxError(" + callback + ")");
			return this;
		}

		/**
		 * Attach a function to be executed whenever an AJAX request fails.
		 * 
		 * @param callback
		 *            callback wicket behavior
		 * @return
		 */
		public JQScriptBuilder ajaxError(AbstractDefaultJQBehavior callback)
		{
			return this.ajaxError(new JQFunction(callback));
		}

		/**
		 * Attach a function to be executed before an AJAX request is sent.
		 * 
		 * @param callback
		 *            callback function
		 * @return
		 */
		public JQScriptBuilder ajaxSend(JQFunction callback)
		{
			this.scriptBuilder.append(".ajaxSend(" + callback + ")");
			return this;
		}

		/**
		 * Attach a function to be executed before an AJAX request is sent.
		 * 
		 * @param callback
		 *            callback wicket behavior
		 * @return
		 */
		public JQScriptBuilder ajaxSend(AbstractDefaultJQBehavior callback)
		{
			return this.ajaxSend(new JQFunction(callback));
		}

		/**
		 * Attach a function to be executed whenever an AJAX request begins and there is none already active.
		 * 
		 * @param callback
		 *            callback function
		 * @return
		 */
		public JQScriptBuilder ajaxStart(JQFunction callback)
		{
			this.scriptBuilder.append(".ajaxStart(" + callback + ")");
			return this;
		}

		/**
		 * Attach a function to be executed whenever an AJAX request begins and there is none already active.
		 * 
		 * @param callback
		 *            callback wicket behavior
		 * @return
		 */
		public JQScriptBuilder ajaxStart(AbstractDefaultJQBehavior callback)
		{
			return this.ajaxStart(new JQFunction(callback));
		}

		/**
		 * Attach a function to be executed whenever all AJAX requests have ended.
		 * 
		 * @param callback
		 *            callback function
		 * @return
		 */
		public JQScriptBuilder ajaxStop(JQFunction callback)
		{
			this.scriptBuilder.append(".ajaxStop(" + callback + ")");
			return this;
		}

		/**
		 * Attach a function to be executed whenever all AJAX requests have ended.
		 * 
		 * @param callback
		 *            callback wicket behavior
		 * @return
		 */
		public JQScriptBuilder ajaxStop(AbstractDefaultJQBehavior callback)
		{
			return this.ajaxStop(new JQFunction(callback));
		}

		/**
		 * Attach a function to be executed whenever an AJAX request completes successfully.
		 * 
		 * @param callback
		 *            callback function
		 * @return
		 */
		public JQScriptBuilder ajaxSuccess(JQFunction callback)
		{
			this.scriptBuilder.append(".ajaxSuccess(" + callback + ")");
			return this;
		}

		/**
		 * Attach a function to be executed whenever an AJAX request completes successfully.
		 * 
		 * @param callback
		 *            callback wicket behavior
		 * @return
		 */
		public JQScriptBuilder ajaxSuccess(AbstractDefaultJQBehavior callback)
		{
			return this.ajaxSuccess(new JQFunction(callback));
		}

		/**
		 * Setup global settings for AJAX requests.
		 * 
		 * @param options
		 *            ajax options
		 */
		public void ajaxSetup(JQAjaxOptions options)
		{
			this.scriptBuilder.append(".ajaxSetup(" + options + ")");
		}

		/**
		 * Serializes a set of input elements into a string of data.<br>
		 * This will serialize all given elements.
		 * 
		 * @return
		 */
		public JQScriptBuilder serialize()
		{
			this.scriptBuilder.append(".serialize()");
			return this;
		}

		/**
		 * Serializes all forms and form elements like serialize() but returns a JSON data structure for you to work with.
		 * 
		 * @return
		 */
		public JQScriptBuilder serializeArray()
		{
			this.scriptBuilder.append(".serializeArray()");
			return this;
		}

		/**
		 * States if the current page, in the user's browser, is being rendered using the <a hre="http://www.w3.org/TR/REC-CSS2/box.html">W3C CSS Box Model</a>
		 * 
		 * @return
		 */
		public JQScriptBuilder boxModel()
		{
			this.scriptBuilder.append(".boxModel");
			return this;
		}

		/**
		 * Contains flags for the useragent, read from navigator.userAgent.<br>
		 * Available flags are: * safari * opera * msie * mozilla<br>
		 * This property is available before the DOM is ready, therefore you can use it to add ready events only for certain browsers.<br>
		 * There are situations where object detection is not reliable enough, in such cases it makes sense to use browser detection.<br>
		 * A combination of browser and object detection yields quite reliable results. <br>
		 * 
		 * @return
		 */
		public JQScriptBuilder browser()
		{
			this.scriptBuilder.append(".browser");
			return this;
		}

		/**
		 * The version number of the rendering engine for the user's browser.<br>
		 * Here are some typical results:<br>
		 * Internet Explorer: 6.0, 7.0 <br>
		 * Mozilla/Firefox/Flock/Camino: 1.7.12, 1.8.1.3<br>
		 * Opera: 9.20<br>
		 * Safari/Webkit: 312.8, 418.9
		 * 
		 * @return
		 */
		public JQScriptBuilder browserVersion()
		{
			this.scriptBuilder.append(".browser.version");
			return this;
		}

		// TODO ARRAY AND OBJECT OP SUPPORT + FUNCTION TEST

		/**
		 * Remove the whitespace from the beginning and end of a string. Uses a regular expression to remove whitespace from the given string.
		 * 
		 * @param str
		 *            string to trim
		 * @return
		 */
		public JQScriptBuilder trim(String str)
		{
			this.scriptBuilder.append(".trim('" + str + "')");
			return this;
		}

		/**
		 * Builds the function chain
		 * 
		 * @return
		 */
		public String build()
		{
			Character c = this.scriptBuilder.charAt(this.scriptBuilder.length() - 1);
			if (c.toString() != ";")
			{
				this.scriptBuilder.append(";");
			}
			return this.toString();
		}

		@Override
		public String toString()
		{
			return this.scriptBuilder.toString();
		}
	}
}